package com.qyb.base.java8.chap5;




import com.qyb.base.java8.bean.Trader;
import com.qyb.base.java8.bean.Transaction;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.*;

public class PuttingIntoPractice{
    public static void demo1(){
        Trader raoul = new Trader("Raoul", "Cambridge");
        Trader mario = new Trader("Mario","Milan");
        Trader alan = new Trader("Alan","Cambridge");
        Trader brian = new Trader("Brian","Cambridge");
		
		List<Transaction> transactions = Arrays.asList(
            new Transaction(brian, 2011, 300), 
            new Transaction(raoul, 2012, 1000),
            new Transaction(raoul, 2011, 400),
            new Transaction(mario, 2012, 710),	
            new Transaction(mario, 2012, 700),
            new Transaction(alan, 2012, 950)
        );	
        
        
        // Query 1: Find all transactions from year 2011 and sort them by value (small to high).
        // 找出2011年发生的所有交易，并按交易额排序（从低到高）。
        List<Transaction> tr2011 = transactions.stream()
                                               .filter(transaction -> transaction.getYear() == 2011)//给filter传递一个谓词来选择2011年的交易
                                               .sorted(comparing(Transaction::getValue))//按照交易额进行排序
                                               .collect(toList());           //将生成的Stream中的所有元素收集到 一个List中
        System.out.println(tr2011);

        // Query 2: What are all the unique cities where the traders work?
        // 交易员都在哪些不同的城市工作过？
        List<String> cities = 
            transactions.stream()
                        .map(transaction -> transaction.getTrader().getCity())//提取与交易相关的每位交易员的所在城市
                        .distinct()                    //只选择互不相同的城市
                        .collect(toList());
        System.out.println(cities);

        //这里还有一个新招：你可以去掉distinct()，改用toSet()，这样就会把流转换为集合。
        //你在第6章中会了解到更多相关内容。
        Set<String> cities1 =
                transactions.stream()
                        .map(transaction -> transaction.getTrader().getCity())
                        .collect(toSet());
        System.out.println(cities1);

        // Query 3: Find all traders from Cambridge and sort them by name.
        // 查找所有来自于剑桥的交易员，并按姓名排序。
        List<Trader> traders = 
            transactions.stream()
                        .map(Transaction::getTrader)   //从交易中提取所有交易员
                        .filter(trader -> trader.getCity().equals("Cambridge"))//仅选择位于剑桥的交易员
                        .distinct()                          //确保没有任何重复
                        .sorted(comparing(Trader::getName))// 对生成的交易员流按 照姓名进行排序
                        .collect(toList());
        System.out.println(traders);
        
        
        // Query 4: Return a string of all traders’ names sorted alphabetically.
        //返回所有交易员的姓名字符串，按字母顺序排序。
        String traderStr = 
            transactions.stream()
                        .map(transaction -> transaction.getTrader().getName())//提取所有交易员姓名，生成一个Strings构成的Stream
                        .distinct()          //只选择不相同的姓名
                        .sorted()            //对姓名按字母顺序排序
                        .reduce("", (n1, n2) -> n1 + n2);//逐个拼接每个名字，得到一个将所有名字连接起来的String
        System.out.println(traderStr);

        //请注意，此解决方案效率不高（所有字符串都被反复连接，每次迭代的时候都要建立一个新
        //的String对象）。下一章中，你将看到一个更为高效的解决方案，它像下面这样使用joining（其
        //内部会用到StringBuilder）：
        String traderStr1 =
                transactions.stream()
                        .map(transaction -> transaction.getTrader().getName())
                        .distinct()
                        .sorted()
                        .collect(joining());
        System.out.println(traderStr1);

        // Query 5: Are there any trader based in Milan?
        // 有没有交易员是在米兰工作的？
        boolean milanBased =
            transactions.stream()
                        .anyMatch(transaction -> transaction.getTrader().getCity().equals("Milan")//把一个谓词传递给anyMatch，检查是否有交易员在米兰工作
                                 );
        System.out.println(milanBased);

        // Query 6: 打印生活在剑桥的交易员的所有交易额。
        transactions.stream()
                .filter(t -> "Cambridge".equals(t.getTrader().getCity()))//选择住在剑桥的交易员所进 行的交易
                .map(Transaction::getValue)              //提取这些交易的交易额
                .forEach(System.out::println);          //打印每个值

        // Query 7: Update all transactions so that the traders from Milan are set to Cambridge.
        // 更新所有交易员为剑桥
        transactions.stream()
                    .map(Transaction::getTrader)
                    .filter(trader -> trader.getCity().equals("Milan"))
                    .forEach(trader -> trader.setCity("Cambridge"));
        System.out.println(transactions);
        
        
        // Query 8: What's the highest value in all the transactions?
        // 所有交易中，最高的交易额是多少？
        int highestValue = 
            transactions.stream()
                        .map(Transaction::getValue)        //提取每项交易的交易额
                        .reduce(0, Integer::max); //计算生成的流中的最大值

        Optional<Integer> highestValue1 =
                transactions.stream()
                        .map(Transaction::getValue)
                        .reduce(Integer::max);

        System.out.println(highestValue);

        // Query 9:找到交易额最小的交易。
        Optional<Transaction> smallestTransaction =
                transactions.stream()
                        .reduce((t1, t2) ->
                                t1.getValue() < t2.getValue() ? t1 : t2);//通过反复比较每个交易的交易额，找出最小的交易

        // 你还可以做得更好。流支持min和max方法，它们可以接受一个Comparator作为参数，指定
        // 计算最小或最大值时要比较哪个键值：
        Optional<Transaction> smallestTransaction1 =
                transactions.stream().min(comparing(Transaction::getValue));
    }
}